/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "UI.h"
#include "布局.h"

#include "intern/ui散列视口.h"
#include "intern/ui容器部件.h"
#include "intern/ui3D视口.h"
#include "intern/ui图像视频.h"
#include "intern/ui标量部件.h"
#include "intern/ui列表.h"
#include "intern/ui按钮.h"
#include "intern/事件处理.h"

#include "实例部件/ui文件对话框.h"
#include "实例部件/ui矢量数据部件.h"

#include "窗口/窗口.h"


#include "core/属性.h"
#include "core/时间.h"
//#include <WinUser.h>
//#include <ppl.h>


#include <vulkan/vulkan.h>
#include <几何图形/图形相交.h>
#include <公共函数.h>
#include <time.h>

using namespace std;

static uint8		g_焦点数量 = 0;
static C_Widget*	g_焦点组件[128] = {};
static C_Widget*	g_上一轮焦点组件 = 0;


static float64 gdur;
static clock_t g时间start = clock();
static clock_t g时间end;
static float32 g双击时间 = 0;

static std::vector<S_纹理填充列队>				g_纹理填充列队;

static std::map<uint64, fp_Widget全局按键按下>	g_全局按键事件;
static std::vector<S_键盘键位映射>				g_全局键盘事件;
static std::vector<S_鼠标键位映射>				g_全局鼠标事件;
static uint8 g键盘按下数量 = 0;
static uint8 g鼠标按下数量 = 0;
static uint8 g键盘以按下键[4] = {};


//static C_Widget*	g上一次焦点组件[128] = {};
//static int16		g上一次焦点组件数量 = 0;



static void f_release子部件(C_Widget* w) {
	uint32 num = w->m_子组件.size();
	if (num) {
		auto* p = w->m_子组件.data();

		for (uint16 i = 0; i < num; ++i) {
			f_release子部件(p[i]);
			delete p[i];
			p[i] = nullptr;
		}

		w->m_子组件.clear();
	}
}



C_Widget管理* f_create组件管理(S_UI创建环境& Ctx) {
	auto gm = new C_Widget管理(Ctx);
	gm->m_Root = 0;
	return gm;
}

void f_release组件管理(C_Widget管理* gm) {
	for (auto& w : gm->m_根部件切换组) {
		delete w;
	}
	gm->m_根部件切换组.clear();
	delete gm;
}







C_Widget* f_创建拖拽面板(const vec2& pos, const vec2& size) {
	C_Widget* w = new C_Widget();
	w->f_setPos(pos);
	w->f_setSize(size);

	return w;
}

C_Widget* f_创建填充布局(const vec2& pos, const vec2& size, const vec4& 边距){
	C_Widget* w = new C_Widget();
	w->mf_布局Fun = f_填充布局;
	return w;
}

C_Widget* f_创建分割布局(const vec2& pos, const vec2& size, E_方向 方向) {
	return nullptr;
}

C_Widget* f_创建框架布局(const vec2& pos, const vec2& size, const vec4& 边距) {
	C_Widget* w = new C_Widget();
	w->f_setPos(pos);
	w->f_setSize(size);

	return w;
}

C_Widget* f_创建根部件(const vec2& 位置比, const vec2& 大小比, E_布局方式 方式) {
	C_Widget* w = new C_Widget();
	w->m_TypeName = DEF_WIDGET_根布局;
	w->m_布局方式 = 方式;
	switch (方式) {
	case E_布局方式::e_填充布局:
		w->mf_布局Fun = f_填充布局;
		break;
	case E_布局方式::e_VBOX布局:
		w->mf_布局Fun = f_VBOX布局;
		break;
	case E_布局方式::e_网格:
		w->mf_布局Fun = f_Layout_网格;
		break;
	default:
		break;
	}
	return w;
}

C_Widget* f_ui_创建分割窗口(const std::vector<C_Widget*>& ws, E_方向 dir, const std::vector<float32>& 分割比, S_UI创建环境& ctx) {
	auto* w = new C_分割框(ctx, dir);

	uint32 分割数量 = ws.size();

	float32 比例 = 1.0 / (分割数量);
	for (uint32 i = 0; i < 分割数量; ++i) {
		w->f_add分割(ws[i], 分割比[i]);
	}
	
	return w;
}

E_方向 f_ui_get分割框排列方向(C_Widget* self) {
	return static_cast<C_分割框*>(self)->m_排列方向;
}

std::vector<float32> f_ui_get分割框分割比例(C_Widget* self) {
	return static_cast<C_分割框*>(self)->m_分割比例;
}

C_Widget* f_散列视口(const vec2& pos, const vec2& size, S_UI创建环境& ctx) {
	C_Widget* w = new C_散列视口(ctx);
	w->f_setPos(pos);
	w->f_setSize(size);

	w->mf_布局Fun = f_散列布局;
	return w;
}

C_Widget* f_ui_创建3D视口(S_Scene* scene, const vec2& size, S_UI创建环境& ctx, S_设备环境& Ctx3D) {
	C_3D视口* w = new C_3D视口(ctx, Ctx3D);
	w->f_setSize(size);
	w->m_Scene = scene;

	//gm.m_帧渲染层.push_back(w);
	w->m_TypeName = "3D视口";
	return w;
}

void f_ui_3D视口绑定场景更新回调(C_Widget* self, fp_Widget更新 func) {
	static_cast<C_3D视口*>(self)->mf_场景外部更新回调 = func;
}

void f_UI_切换3D视口渲染模式(C_Widget* self, E_物体显示模式 type) {
	switch (type)
	{
	case E_物体显示模式::e_线:
	case E_物体显示模式::e_面:
	case E_物体显示模式::e_线面: {
		static_cast<C_3D视口*>(self)->m_开启光追 = false;
		break;
	}
	case E_物体显示模式::e_渲染: {
		static_cast<C_3D视口*>(self)->m_开启光追 = true;
		break;
	}
	default:
		break;
	}
}

C_Widget* f_ui_创建菜单(E_方向 dir, S_菜单创建参数& ini, S_UI创建环境& ctx) {
	auto ui菜单 = new C_菜单(dir, ctx);
	f_ui_添加菜单项(ui菜单, ini, ctx, 1);

	if (dir == E_方向::e_纵向) {
		//f_顶层菜单画布构建(ui菜单, 1, ctx);
	}
	
	return ui菜单;
}

C_Widget* f_ui_创建列表(E_列表显示模式 模式, S_UI创建环境& ctx) {
	C_列表框* listbox = new C_列表框(ctx, 1, 模式);

	return listbox;
}


C_Widget* f_ui_创建多页面(S_UI创建环境& ctx, E_方向 标签方向, std::vector<C_Widget*>& ws) {
	auto 多页面 = new C_多页面(ctx, 标签方向);
	
	for(auto& e: ws) 多页面->f_add页面(e, -1);
	
	return 多页面;
}

C_Widget* f_ui_创建多页面(S_UI创建环境& ctx, E_方向 标签方向, std::vector<std::wstring>& ws) {
	auto 多页面 = new C_多页面(ctx, 标签方向);
	for (auto& e : ws) {
		多页面->f_add页面(e, -1);
	}
	return 多页面;
}

C_Widget* f_ui_创建图像视口(S_UI创建环境& ctx, uint8 缓存数量) {
	auto 视频框 = new C_视频框(ctx, 缓存数量);
	
	return 视频框;
}

C_Widget* f_ui_创建按钮(S_UI创建环境* ctx, S_Props* op) {
	auto* 按钮 = new C_按钮(ctx, op);
	if (op) {
		op->m_UI->m_部件 = 按钮;
	}
	return 按钮;
}


C_Widget* f_ui_创建bool值编辑框(S_UI创建环境& ctx, S_Props& prop, fp_Widget布尔值回调 func) {
	auto* w = new C_编辑框Bool(ctx, prop);
	w->m_Value = prop;
	w->mf_值改变回调 = func;

	if ((*((bool*)w->m_Value.m_Value))) {
		w->m_颜色A = S_UI主题::uic_值编辑框文字焦点背景;
	} else {
		w->m_颜色A = S_UI主题::uic_值编辑框背景;
	}

	return w;
}

C_Widget* f_ui_创建vec编辑框(S_UI创建环境& ctx, S_Props& prop, fp_Widget文本回调 f文本输入, fp_Widget文本输入完成 f输入完成, fp_Widget鼠标按键 f鼠标点击) {
	C_Vec* w = new C_Vec(E_方向::e_纵向, prop, ctx);
	
	auto e = (C_文本框**)(w->m_子组件.data());
	
	for (uint8 i = 0; i < prop.m_值元素个数; ++i) {
		e[i]->mf_文本输入 = f文本输入;
		e[i]->mf_文本输入完成 = f输入完成;
		e[i]->mf_鼠标按键点击 = f鼠标点击;
		e[i]->m_实例ID = i;
	}

	return w;
}

C_Widget* f_ui_创建vec编辑框(S_UI创建环境& ctx, S_Props& prop) {
	C_Vec* w = new C_Vec(E_方向::e_纵向, prop, ctx);
	auto e = (C_文本框**)(w->m_子组件.data());
	for (uint8 i = 0; i < prop.m_值元素个数; ++i) {
		e[i]->m_实例ID = i;
	}
	return w;
}

C_Widget* f_ui_创建编辑框(S_UI创建环境& ctx, fp_Widget文本回调 f文本输入, fp_Widget文本输入完成 f输入完成, std::string 字体名称) {
	C_文本编辑框* edit = new C_文本编辑框(ctx, 字体名称);
	C_滚动框* box = new C_滚动框(ctx, true, true, edit);
	edit->mf_文本输入 = f文本输入;
	edit->mf_文本输入完成 = f输入完成;
	return box;
}

C_Widget* f_ui_创建可编辑文本下拉框(S_UI创建环境& ctx) {
	C_下拉列表框* list = new C_下拉列表框(ctx);
	return list;
}

C_Widget* f_ui_创建路径编辑框(S_UI创建环境& ctx, C_Widget* 对话框, fp_Widget绘制调整回调 绘制调整回调) {
	assert(dynamic_cast<C_文件对话框*>(对话框));
	C_路径编辑器* box = new C_路径编辑器(ctx, (C_文件对话框*)对话框);
	box->m_子组件[0]->mf_当前部件属性修改 = 绘制调整回调;
	box->m_子组件[1]->mf_当前部件属性修改 = 绘制调整回调;
	return box;
}

C_Widget* f_ui_创建行文本编辑框(S_UI创建环境& ctx) {
	C_行编辑框* box = new C_行编辑框(ctx);
	return box;
}

std::wstring f_ui_取行编辑框文本(C_Widget* self) {
	return static_cast<C_文本框*>(self)->m_Text;
}

C_Widget* f_ui_创建颜色选框(S_UI创建环境& ctx, S_Props& prop) {
	return new C_RGBA8选择框(ctx, prop);
}


void f_ui_连接vecGPU参数修改回调(C_Widget* w, fp_Widget变换修改 fc) {
	C_Vec* v = dynamic_cast<C_Vec*>(w);

	auto e = (C_文本框**)(w->m_子组件.data());
	for (uint8 i = 0; i < v->m_Value.m_值元素个数; ++i) {
		e[i]->mf_变换修改 = fc;
	}
	
	//e[0]->mf_变换修改 = fc;
	//e[1]->mf_变换修改 = fc;
	//e[2]->mf_变换修改 = fc;
}

void f_ui_连接vec3GPU编辑回调(C_Widget* w, fp_Widget文本回调 f文本输入, fp_Widget文本输入完成 f输入完成, fp_Widget鼠标按键 f鼠标点击) {
	//C_Vec3* w = new C_Vec3(E_方向::e_纵向, prop, ctx);
	//prop.m_部件 = w;

	auto e = (C_文本框**)(w->m_子组件.data());

	e[0]->mf_文本输入 = f文本输入;
	e[0]->mf_文本输入完成 = f输入完成;
	e[0]->mf_鼠标按键点击 = f鼠标点击;
	e[0]->m_实例ID = 0;

	e[1]->mf_文本输入 = f文本输入;
	e[1]->mf_文本输入完成 = f输入完成;
	e[1]->mf_鼠标按键点击 = f鼠标点击;
	e[1]->m_实例ID = 1;

	e[2]->mf_文本输入 = f文本输入;
	e[2]->mf_文本输入完成 = f输入完成;
	e[2]->mf_鼠标按键点击 = f鼠标点击;
	e[2]->m_实例ID = 2;

}

void f_ui_连接鼠标移入移出回调(C_Widget* self, fp_Widget鼠标 inFunc, fp_Widget鼠标 outFunc, const uint32 指定层级, uint32 depth) {
	if (指定层级 == depth) {
		self->mf_鼠标进入 = inFunc;
		self->mf_鼠标离开 = outFunc;
	}
	else {
		auto e = self->f_get更新部件();
		for (uint32 i = 0; i < e.m_Num; ++i) {
			f_ui_连接鼠标移入移出回调(e.m_W[i], inFunc, outFunc, 指定层级, depth + 1);
		}
	}
}

C_Widget* f_ui_创建文件对话框(fp_文件处理回调 fun, std::string 初始路径, S_UI创建环境& ctx) {
	auto* filedialog = new C_文件对话框(ctx);
	filedialog->mf_文件处理回调 = fun;

	return filedialog;
}

void f_ui_设置文件对话框类型(C_Widget* fw, E_对话框类型 type) {
	C_文件对话框* filedialog = dynamic_cast<C_文件对话框*>(fw);

	if (filedialog) {
		//filedialog->m_文件处理方式 = type;
		filedialog->f_set对话框模式(type);
	}
}










C_Widget* f_ui_get滚动框视口(C_Widget* self) {
	C_滚动框* sbox = dynamic_cast<C_滚动框*>(self);
	if(sbox) return sbox->m_View;
	return nullptr;
}

std::wstring f_ui_get编辑框文本(C_Widget* self) {
	C_文本框* box = dynamic_cast<C_文本框*>(self);
	return box->m_Text;
}

C_文本框* f_ui_from滚动框取文本视口(C_Widget* self) {
	C_滚动框* sbox = dynamic_cast<C_滚动框*>(self);
	if (sbox) return dynamic_cast<C_文本框*>(sbox->m_View);
	return nullptr;
}








void f_ui_设置按钮操作符(C_Widget* self, S_Props& op) {
	C_按钮* but = dynamic_cast<C_按钮*>(self);

	if (but) {
		but->m_Op = op;
	}
}



void f_ui_添加菜单项(C_Widget* self, S_菜单创建参数 pip, S_UI创建环境& ctx, uint16 layers) {
	C_菜单* menu = dynamic_cast<C_菜单*>(self);
	
	if (menu) {
		menu->m_layer = layers;
		uint32 ID = 0;
		for (auto& item : pip.item) {
			C_菜单项* sonItem = menu->f_添加项(item.name, item.ico);

			sonItem->mf_菜单事件 = pip.mf_菜单项点击;
			sonItem->m_ICO = item.ico;
			sonItem->m_实例ID = ID;
			++ID;

			if (item.子菜单参数) {
				C_菜单* sonMenu = sonItem->f_添加子菜单(layers + 1, ctx);
				S_菜单创建参数& 子项参数 = *((S_菜单创建参数*)item.子菜单参数);
				f_ui_添加菜单项(sonMenu, 子项参数, ctx, layers + 1);
			}
		}
	}
}

void f_ui_打开菜单(C_Widget* self, vec2 pos) {
	C_菜单* menu = dynamic_cast<C_菜单*>(self);

	if (menu) {
		//auto* t = f_widget_getBack();
		f_widget_顶层窗口_push(menu, menu->m_layer-1);

		pos = f_菜单坐标矫正(menu, pos);
		menu->f_打开(pos);

	}
}

void f_ui_打开对话框(C_Widget管理* gm, C_Widget* w, E_对话框类型 type, fp_文件处理回调 fun, std::string path, std::string 后缀) {
	C_文件对话框* dig = dynamic_cast<C_文件对话框*>(w);
	if (dig) {
		//dig->m_文件路径 = f_StringToWString(path);
		dig->m_路径 = path;
		dig->m_文件后缀 = 后缀;
		dig->mf_文件处理回调 = fun;

		dig->f_set对话框模式(type);
	}

	f_ui_switchRootWidget(gm, w->m_实例ID);
}

void f_ui_关闭对话框(C_Widget管理* gm, C_Widget* w, uint16 id) {
	f_ui_switchRootWidget(gm, id);
}

uint32 f_ui_多页面添加页面(C_Widget* w, C_Widget* page, int8 loc) {
	C_多页面* mpage = dynamic_cast<C_多页面*>(w);
	mpage->f_add页面(page, loc);
	return mpage->m_分页面.size();
}

void f_ui_设置多页面头(C_Widget* w, vec2 size) {
	auto* page = dynamic_cast<C_多页面*>(w);
	page->m_头大小 = size;
}

void f_ui_设置多页面标签文本(C_Widget* w, uint16 id, const std::wstring& text) {
	auto* page = dynamic_cast<C_多页面*>(w);
	if (page) {
		if (id < page->m_子组件.size()) {
			page->m_子组件[id]->m_WName = text;
		}
	}
}

void f_ui_set图像视口纹理(C_Widget* w, S_纹理* tex, uint32 frameOffset) {
	auto* view = dynamic_cast<C_视频框*>(w);
	if (view) {
		view->f_set槽纹理(tex, 0);
		//f_vg_set纹理(view->m_笔刷, 0, tex);
	}
}

void f_ui_图像视口填充捕捉点(C_Widget* w, std::vector<S_Rect2Df>& 点坐标, std::vector<S_RGBA8UI>& 点颜色) {
	auto* view = dynamic_cast<C_视频框*>(w);
	if (view) {
		f_视频框_填充视频捕捉点(view, 点坐标, 点颜色);
	}
}

void f_ui_图像视口_设置选区(C_Widget* w, const S_Rect2Df& 点坐标, const S_RGBA8UI& 点颜色) {
	auto* view = dynamic_cast<C_视频框*>(w);
	if (view) {
		f_视频框_设置选取(view, 点坐标, 点颜色);
	}
}

void f_ui_图像视口_关闭选区(C_Widget* w) {
	auto* view = dynamic_cast<C_视频框*>(w);
	if (view) {
		f_视频框_关闭选取(view);
	}
}

void f_ui_设置bool值编辑框引用值(C_Widget* w, S_Props prop) {
	auto* view = dynamic_cast<C_编辑框Bool*>(w);
	if (view) {
		view->m_Value = prop;
		view->m_Value.m_UI->m_部件 = view;

		view->f_刷新();
	}
}

void f_ui_文本框插入行文本(C_Widget* w, std::wstring text, int32 行) {
	C_文本编辑框* box = dynamic_cast<C_文本编辑框*>(w);

	S_文档文本 块;
	块.m_Text = text;
	box->m_文档->m_字文本块.push_back(块);
}

bool f_ui_编辑框开关编辑(C_Widget* self, bool open)  {
	return false;
}

void f_ui_set数值部件布尔值(C_Widget* self) {
	C_编辑框Bool* box = dynamic_cast<C_编辑框Bool*>(self);
	if (box) {
		(*((bool*)box->m_Value.m_Value)) = !(*((bool*)box->m_Value.m_Value));
	}
}

bool f_ui_文本部件完成输入(C_Widget* self) {
	if (C_文本框::g当前操作文本框 && C_文本框::g当前操作文本框 != self) {
		C_文本框::g当前操作文本框->f_输入完成();
	}
	return false;
}

void f_ui_set文本框框选回调(C_Widget* self, fp_Widget更新 选时, fp_Widget更新 选后) {
	C_文本框* box = dynamic_cast<C_文本框*>(self);
	if (box) {
		box->mf_框选时回调 = 选时;
		box->mf_框选后回调 = 选后;
	}
}

vec2 f_ui_行编辑框光标位置(C_Widget* self) {
	C_文本框* box = dynamic_cast<C_文本框*>(self);
	//box->f_set对齐偏移();
	return box->g_光标绘制位置;
	//return box->m_Pos + vec2{ box->g_光标位置.x, 0 };
}

bool f_ui_文本部件全选(C_Widget* self, uvec2 range) {
	C_文本框* box = dynamic_cast<C_文本框*>(self);

	box->m_行选框左边和右边.x;

	return false;
}

void f_ui_set文本编辑框文本(C_Widget* self, S_文档文本& txt) {
	auto box = dynamic_cast<C_文本编辑框*>(self);
	box->m_光标 = {};
	box->m_选取 = {};
	box->m_文档->m_文本块 = txt.m_文本块;
	box->m_文档->m_Color = txt.m_Color;
}

void f_ui_setVec布局方向(C_Widget* self, E_方向 方向) {
	assert(dynamic_cast<C_Vec*>(self));
	//((C_Vec*)self)->m_方向 = 方向;
	((C_Vec*)self)->f_切换布局方向(方向);
	self->m_绘制属性更新 = true;
}

void f_ui_set多页面添加事件(C_Widget* self, fp_Widget鼠标按键 切换回调, vec2 size) {
	C_多页面* mpage = dynamic_cast<C_多页面*>(self);

	mpage->m_添加按钮 = (C_按钮*)f_ui_创建按钮(nullptr, 0);
	mpage->m_添加按钮->m_实例ID = 0xffffffff;
	mpage->m_添加按钮->f_setSize(size);
	mpage->m_添加按钮->mf_鼠标按键点击 = 切换回调;

	mpage->f_添加子组件(mpage->m_添加按钮, -1);
}

void f_ui_set多页面当前页面(C_Widget* self, uint32 id) {
	assert(dynamic_cast<C_多页面*>(self));
	static_cast<C_多页面*>(self)->f_set页面(DEF_Min(id, static_cast<C_多页面*>(self)->m_分页面.size() - 1));
	//static_cast<C_多页面*>(self)->m_当前页面ID = DEF_Min(id, static_cast<C_多页面*>(self)->m_分页面.size());
}



void f_ui_3D视口渲染(C_Widget* self) {
	static_cast<C_3D视口*>(self)->f_渲染();
	//std::cout << "三维渲染" << std::endl;
}

S_Rect2Df f_ui_get视口(C_Widget* self) {
	return { {0,0}, {self->m_Size.x, self->m_Size.y} };
}

void f_ui_set3D视口部件帧绘制(C_Widget* self, bool 暂停) {
	C_3D视口* view = dynamic_cast<C_3D视口*>(self);
	if (view) {
		if (暂停) {
			view->m_锁.lock();
		} else {
			view->m_锁.unlock();
		}
	}
}

void f_ui_set子部件的画布所在部件(C_Widget* self, C_Widget* 画布所在部件) {
	self->m_画布所在部件 = 画布所在部件;

	auto e = self->f_get更新部件();

	for (uint32 i = 0; i < e.m_Num; ++i) {
		f_ui_set子部件的画布所在部件(e.m_W[i], 画布所在部件);
	}
}

float32* f_ui_getVec数据指针(C_Widget* self) {
	return (float32*)(((C_Vec*)self)->m_Value.m_Value);
}

float32* f_ui_getVec数据指针(C_Widget* self, uint8 loc) {
	return (float32*)(((C_Vec*)self)->m_Value.m_Value);
}

S_Props* f_ui_getVec数据(C_Widget* self) {
	return &(((C_Vec*)self)->m_Value);
}

S_文档文本* f_ui_get文档数据(C_Widget* self) {
	C_滚动框* box = dynamic_cast<C_滚动框*>(self);
	if (box) {
		C_文本编辑框* v = dynamic_cast<C_文本编辑框*>(box->m_View);
		if (v) {
			return v->m_文档;
		}
	}
	return nullptr;
}

uint32 f_ui_get文档文本总字符数(const S_文档文本& doc) {
	uint32 num = 0;
	uint32 行数量 = doc.m_文本块.size();
	for (uint32 y = 0; y < 行数量; ++y) {
		num += doc.m_文本块[y].size();
	}
	return num;
}

bool f_ui_路径编辑框打开对话框(C_Widget* self, C_Widget管理* gm) {
	assert(dynamic_cast<C_路径编辑器*>(self));
	C_路径编辑器* box = (C_路径编辑器*)self;

	f_ui_switchRootWidget(gm, box->mui_对话框->m_实例ID);
	
	return true;
}

bool f_ui_路径编辑框是否打开(C_Widget* self) {
	C_路径编辑器* box = (C_路径编辑器*)self;
	return box->m_对话框是否打开;
}



void f_ui_bind行编辑框属性(C_Widget* self, S_Props& p) {
	auto* box = dynamic_cast<C_行编辑框*>(self);
	box->m_Value = p;
	box->m_Text = f_prop_Str(box->m_Value);
	box->m_绘制属性更新 = true;
}

void f_ui_bind文本编辑框文档(C_Widget* self, S_文档文本* doc) {
	auto* box = dynamic_cast<C_文本框*>(self);
	if (box) {
		box->m_文档 = doc;
		box->m_光标 = {0,0};
		box->m_选取 = { {},{} };
	}
}

void f_ui_bind路径编辑框属性(C_Widget* self, S_Props* p) {
	assert(dynamic_cast<C_路径编辑器*>(self));
	((C_路径编辑器*)(self))->m_路径 = p;
	self->m_绘制属性更新 = true;

	((C_行编辑框*)(((C_路径编辑器*)(self))->m_子组件[0]))->f_set文本(f_prop_Path(*(p)));
	((C_行编辑框*)(((C_路径编辑器*)(self))->m_子组件[0]))->m_Value = *p;
}

void f_ui_set路径编辑框对话框类型(C_Widget* self, E_对话框类型 对话框类型) {
	((C_路径编辑器*)(self))->m_对话框类型 = 对话框类型;
}

void f_ui_set路径编辑框对话框后缀(C_Widget* self, std::string 后缀) {
	C_路径编辑器* 路径框 = dynamic_cast<C_路径编辑器*>(self);
	if (路径框) {
		路径框->mui_对话框->m_文件后缀 = 后缀;
	}
	//((C_路径编辑器*)(self))->mui_对话框->m_文件后缀 = 后缀;
}

void f_部件设置布局(C_Widget* w, E_布局方式 方式) {
	switch (方式)
	{
	case E_布局方式::e_HBOX布局:
		break;
	case E_布局方式::e_VBOX布局:
		break;
	case E_布局方式::e_填充布局:
		{
			S_比例布局* l = new S_比例布局();
			l->m_位置比例 = { 0.0f,0.0f };
			l->m_大小比例 = { 1.0f,1.0f };
			//w->m_布局器 = l;
		}
		break;
	case E_布局方式::e_BOX布局:
		break;
	default:
		break;
	}
}


static void f_子组件裁剪(C_Widget* w) {
	if (w->mf_布局Fun)w->mf_布局Fun(w, w->m_子组件.data(), w->m_子组件.size());
	w->f_裁剪();

	if (w->m_被裁剪) return;

	uint32 num = w->m_子组件.size();
	if (!num) return;

	auto* p = w->m_子组件.data();
	for (uint32 i = 0; i < num; ++i) {
		f_子组件裁剪(p[i]);
	}
}

void f_ui_组件布局(C_Widget管理* gm, const vec4& area) {
	//根部件固定设置成窗口大小
	gm->窗口大小 = area;

	/****************************************************************
	*           调整和裁剪顶层窗口
	*****************************************************************/
	auto topWidget = f_widget_getTop();
	for (uint8 i = 0; i < topWidget.m_Num; ++i) {
		topWidget.m_W[i]->f_setSize({ area.z, area.w });
		//topWidget.m_W[i]->m_裁剪大小 = { 0.0f,0.0f, area.z, area.w };
		f_子组件裁剪(topWidget.m_W[i]);
	}


	/****************************************************************
	*           调整和裁剪常规窗口
	*****************************************************************/
	uint32 num = gm->m_根部件切换组.size();
	for (uint8 i = 0; i < num; ++i) {
		gm->m_根部件切换组[i]->f_setSize({ area.z, area.w });
		f_子组件裁剪(gm->m_根部件切换组[i]);
	}
	//Concurrency::parallel_for<uint8>(0, gm->m_根部件切换组.size(), [&](uint8 i) {
	//	gm->m_根部件切换组[i]->f_setSize({ area.z, area.w });
	//	f_子组件裁剪(gm->m_根部件切换组[i]);
	//});
}




static bool f_筛选焦点组件(C_Widget* w, const vec2& point) {
	uint32 num = w->m_子组件.size();
	if (!num) return 0;
	auto p = w->m_子组件.data();


	C_Widget* tem[8];
	for (uint32 depth = 1; ; ++depth) {
		bool 无焦点组件 = true;

		uint32 未被裁剪数量 = 0;
		//for (uint32 i = 0; i < num; ) {
		for (int32 i = num-1; i >= 0; ) {
			//std::cout << "A== " << depth << " == " << int(i) << p[i]->m_Name << std::endl;
			if (!(p[i]->m_被裁剪)) {
				tem[未被裁剪数量] = p[i];
				++未被裁剪数量;
			}

			--i;
			//从8个组件中筛选在坐标点的组件
			if (未被裁剪数量 >= 8 || i < 0) {
				auto id = f_widget_筛选焦点组件_avx(tem, 未被裁剪数量, point);

				未被裁剪数量 = 0;
				if (id >= 0) {
					++C_Widget::g_焦点数量;
					g_焦点组件[depth] = tem[id];

					//子部件绑定到当前层部件指针
					num = tem[id]->m_子组件.size();
					p = tem[id]->m_子组件.data();

					//std::cout << "A== " << depth << " == " << int(i) << tem[id]->m_Name << 无焦点组件 << std::endl;
					无焦点组件 = false;
					break;
				}
			}
		}

		if (无焦点组件) break;
	}
	
	return C_Widget::g_焦点数量;
}

void f_ui_筛选焦点组件(C_Widget管理* gm, const vec2& point) {
	/****************************************************************
	*                   筛选顶层焦点窗口
	*****************************************************************/
	auto topWidget = f_widget_getTop();
	
	auto id = f_widget_筛选焦点组件_avx(topWidget.m_W, topWidget.m_Num, point);
	if (id >= 0) {
		C_Widget::g_焦点数量 = 1;
		g_焦点组件[0] = topWidget.m_W[id];
		
		if (f_筛选焦点组件(topWidget.m_W[id], point)) {
			return;
		}
	}
	
	C_Widget::g_焦点数量 = 1;
	g_焦点组件[0] = gm->m_Root;
	f_筛选焦点组件(gm->m_Root, point);
}





static bool f_执行全局键盘事件(const S_输入环境& input) {
	uint32 num = g_全局键盘事件.size();
	auto* keys = g_全局键盘事件.data();

	//memset(g键盘以按下键, 0, sizeof(uint8) * 4);
	//uint32 记录1 = 0;
	
	for (uint8 i = 0; i < num; ++i) {
		uint8 bit = 0;
		//keys[i].记录 = 0;
		for (uint8 k = 0; k < 4; ++k) {
			if (keys[i].键盘按键[k]) {
				bit |= 1 << k;
				if (f_键盘单个按键状态(input.m_Key.Keys状态, keys[i].键盘按键[k], keys[i].键盘状态[k])) {
					keys[i].记录 |= 1 << k;
				}
			}
			else {
				if (input.m_Key.Keys状态[ keys[i].键盘按键[k] ]) { 
					keys[i].记录 |= 1 << k;
				}
			}
		}


		bool 控制键全部释放 = true;
		for (uint8 k = 0; k < 4; ++k) {
			if (input.m_Key.Keys状态[keys[i].键盘按键[k]] != DEF_按键状态_准备) {
				控制键全部释放 = false;
			}
		}

		if (bit && keys[i].记录 == bit) {
			//计时 = time_开始计时();
			keys[i].记录 = 0;
			keys[i].event(nullptr, 0);
			return true;
		}

		if (控制键全部释放) {
			keys[i].记录 = 0;
		}
	}

	return false;
}


//static bool f_执行键盘事件(S_键盘键位映射* mk, const uint8* 键盘按键状态) {
//	uint8 bit = 0;
//	
//	for (uint8 k = 0; k < 4; ++k) {
//		if (mk->键盘按键[k]) {
//			bit |= 1 << k;
//			
//			if (f_键盘单个按键状态(键盘按键状态, mk->键盘按键[k], mk->键盘状态[k])) {
//				mk->记录 |= 1 << k;
//			}
//		}
//		else {
//			if (g键盘以按下键[k]) { 
//				mk->记录 |= 1 << k;
//			}
//		}
//	}
//
//	bool 控制键全部释放 = true;
//	for (uint8 k = 0; k < 4; ++k) {
//		if (键盘按键状态[mk->键盘按键[k]] != DEF_按键状态_准备) {
//			控制键全部释放 = false;
//		}
//	}
//	
//	if (bit && mk->记录 == bit) {
//		mk->记录 = 0;
//		return true;
//	}
//	
//	if (控制键全部释放) {
//		mk->记录 = 0;
//	}
//	return false;
//}

//static bool f_执行鼠标事件(S_鼠标键位映射* mk, uint8* 键盘按键状态, uint8* 鼠标按键状态) {
//	uint8 bit = 0;
//	mk->记录 = 0;
//
//	for (uint8 k = 0; k < 4; ++k) {
//		if (mk->键盘按键[k]) {
//			bit |= 1 << k;
//
//			if (f_键盘单个按键状态(键盘按键状态, mk->键盘按键[k], mk->键盘状态[k])) {
//				mk->记录 |= 1 << k;
//			}
//		}
//
//		if (mk->鼠标状态[k]) {
//			bit |= 1 << k + 4;
//
//			if (mk->鼠标状态[k] & 鼠标按键状态[mk->鼠标按键[k]]) {
//				mk->记录 |= 1 << k + 4;
//			}
//		}
//	}
//
//	bool 控制键全部释放 = true;
//	for (uint8 k = 0; k < 4; ++k) {
//		if (键盘按键状态[mk->键盘按键[k]] != DEF_按键状态_准备) {
//			控制键全部释放 = false;
//		}
//		if (键盘按键状态[mk->鼠标按键[k]] != DEF_按键状态_准备) {
//			控制键全部释放 = false;
//		}
//	}
//	
//	if (bit && mk->记录 == bit) {
//		mk->记录 = 0;
//		return true;
//	}
//
//	if (控制键全部释放) {
//		mk->记录 = 0;
//	}
//	return false;
//}

//static bool f_执行拖拽事件(S_拖拽键位映射* mk, uint8* 键盘按键状态, uint8* 鼠标按键状态) {
//	
//	uint8 bit = 0;
//	mk->记录 = 0;
//
//	switch (mk->拖放状态)
//	{
//	case E_拖放状态::e_拖放_开始: {
//		mk->拖放状态 = E_拖放状态::e_拖放_进行;
//		break;
//	}
//	case E_拖放状态::e_拖放_进行: {
//		break;
//	}
//	case E_拖放状态::e_拖放_结束: {
//		break;
//	}
//	default:
//		break;
//	}
//	
//	for (uint8 k = 0; k < 4; ++k) {
//		if (mk->键盘按键[k]) {
//			bit |= 1 << k;
//
//			if (f_键盘单个按键状态(键盘按键状态, mk->键盘按键[k], mk->键盘状态[k])) {
//				mk->记录 |= 1 << k;
//			}
//		}
//		//cout << "mk->鼠标按键[k] = " << mk->鼠标按键[k] << endl;
//		if (mk->鼠标状态[k]) {
//			bit |= 1 << k + 4;
//
//			if (mk->鼠标状态[k] & 鼠标按键状态[mk->鼠标按键[k]]) {
//				mk->记录 |= 1 << k + 4;
//			}
//		}
//	}
//
//
//	bool 控制键全部释放 = true;
//	for (uint8 k = 0; k < 4; ++k) {
//		if (键盘按键状态[mk->键盘按键[k]] != DEF_按键状态_准备) {
//			控制键全部释放 = false;
//		}
//		if (键盘按键状态[mk->鼠标按键[k]] != DEF_按键状态_准备) {
//			控制键全部释放 = false;
//		}
//	}
//	
//
//	if (bit && mk->记录 == bit) {
//		//计时 = time_开始计时();
//		//mk->记录 = 0;
//		mk->状态 = 0;
//		return true;
//	}
//	
//	if (控制键全部释放) {
//		mk->记录 = 0;
//		mk->状态 = 0;
//	}
//
//	return false;
//}




void f_ui_执行输入设备事件(C_Widget管理* gm, const S_输入环境& input) {
	if (!C_Widget::g_焦点数量) return;
	f_widget_set当前窗口矩形(gm->窗口大小);

	gm->鼠标左键按下传递 = true;
	gm->鼠标左键放开传递 = true;
	gm->鼠标右键按下传递 = true;
	gm->鼠标右键放开传递 = true;
	gm->鼠标中键按下传递 = true;
	gm->鼠标中键放开传递 = true;
	
	gm->键盘按键向下传递 = true;
	gm->是否执行UI部件事件 = true;


	gm->mf_输入执行前回调();



	ivec4 Mouse = { input.m_鼠标全局坐标.x, input.m_鼠标全局坐标.y, ((S_鼠标属性*)input.m_鼠标)->lX, ((S_鼠标属性*)input.m_鼠标)->lY };
	//static S_鼠标 鼠标;
	C_Widget::g_鼠标.lZ = ((S_鼠标属性*)input.m_鼠标)->lZ / 120;
	C_Widget::g_鼠标.gPos = { float32(input.m_鼠标全局坐标.x), float32(input.m_鼠标全局坐标.y) };
	C_Widget::g_鼠标.lPos = { float32(((S_鼠标属性*)input.m_鼠标)->lX), float32(((S_鼠标属性*)input.m_鼠标)->lY) };
	C_Widget::g_鼠标.abs = C_Widget::g_鼠标.gPos - C_Widget::g_鼠标.abs;
	C_Widget::g_鼠标.相对窗口偏移.x = gm->窗口大小.x;
	C_Widget::g_鼠标.相对窗口偏移.y = gm->窗口大小.y;
	
	//std::cout<<"C_Widget::g_鼠标.abs = "<< C_Widget::g_鼠标.abs.x << " : " << input.m_鼠标全局坐标.x << std::endl;
	//std::cout << "C_Widget::g_鼠标 = " << ((S_鼠标属性*)input.m_鼠标)->lX << " : " << ((S_鼠标属性*)input.m_鼠标)->lY << std::endl;
	//if ((((S_鼠标属性*)input.m_鼠标)->lX > 1 || ((S_鼠标属性*)input.m_鼠标)->lY > 1) || (((S_鼠标属性*)input.m_鼠标)->lX < -1 || ((S_鼠标属性*)input.m_鼠标)->lY < -1)) {
	uint32 全局鼠标事件数量 = g_全局鼠标事件.size();


	E_事件是否传递 事件是否传递 = E_事件是否传递::e_事件传递_继续;
	bool 鼠标移动了 = false;
	static int32 鼠标移动距离 = 0;
	if (((S_鼠标属性*)input.m_鼠标)->lX || ((S_鼠标属性*)input.m_鼠标)->lY) {
		鼠标移动了 = true;
		//鼠标移动距离 += vec_len(vec2{float32(((S_鼠标属性*)input.m_鼠标)->lX), float32(((S_鼠标属性*)input.m_鼠标)->lY)}) - 鼠标移动距离;
		gm->有输入事件 = true;
	}


	{
		if (((S_鼠标属性*)input.m_鼠标)->rgbButtons[0] ) {
			if(gm->鼠标按键状态[E_Input_鼠标按键::e_左键] == DEF_按键状态_准备) gm->鼠标按键状态[E_Input_鼠标按键::e_左键] = DEF_按键状态_按下;
		}
		else if(gm->鼠标按键状态[E_Input_鼠标按键::e_左键] == DEF_按键状态_按下中) {
			gm->鼠标按键状态[E_Input_鼠标按键::e_左键] = DEF_按键状态_放开;
		}

		if (((S_鼠标属性*)input.m_鼠标)->rgbButtons[1]) {
			if(gm->鼠标按键状态[E_Input_鼠标按键::e_右键] == DEF_按键状态_准备) gm->鼠标按键状态[E_Input_鼠标按键::e_右键] = DEF_按键状态_按下;
		}
		else if (gm->鼠标按键状态[E_Input_鼠标按键::e_右键] == DEF_按键状态_按下中) {
			gm->鼠标按键状态[E_Input_鼠标按键::e_右键] = DEF_按键状态_放开;
		}

		if (((S_鼠标属性*)input.m_鼠标)->rgbButtons[2]) {
			if (gm->鼠标按键状态[E_Input_鼠标按键::e_中键] == DEF_按键状态_准备) gm->鼠标按键状态[E_Input_鼠标按键::e_中键] = DEF_按键状态_按下;
		}
		else if (gm->鼠标按键状态[E_Input_鼠标按键::e_中键] == DEF_按键状态_按下中) {
			gm->鼠标按键状态[E_Input_鼠标按键::e_中键] = DEF_按键状态_放开;
		}

		//std::cout << "((S_鼠标属性*)input.m_鼠标)->lZ = " << ((S_鼠标属性*)input.m_鼠标)->lZ << std::endl;
		if (((S_鼠标属性*)input.m_鼠标)->lZ) {
			if (gm->鼠标按键状态[E_Input_鼠标按键::e_滚轮] == DEF_按键状态_准备) gm->鼠标按键状态[E_Input_鼠标按键::e_滚轮] = DEF_按键状态_按下;
		}
		else if (gm->鼠标按键状态[E_Input_鼠标按键::e_滚轮] == DEF_按键状态_按下中) {
			gm->鼠标按键状态[E_Input_鼠标按键::e_滚轮] = DEF_按键状态_放开;
		}

		//cout << "input.m_Key.Keys[k] == " << int32(input.m_Key.Keys[56]) << endl;
		//static int32 old_a = 0;
		g键盘按下数量 = 0;
		for (uint16 k = 0; k < 256; ++k) {
			if (input.m_Key.Keys[k]) {
				//g键盘以按下键[k] = true;
				//cout << "input.m_Key.Keys[k] == " << int32(input.m_Key.Keys状态[k]) << " : k = " << k << endl;
				if (input.m_Key.Keys状态[k] == DEF_按键状态_准备) input.m_Key.Keys状态[k] = DEF_按键状态_按下;
				++g键盘按下数量;

				gm->有输入事件 = true;
			}
			else {
				//cout << "input.m_Key.Keys[k] == " << int32(input.m_Key.Keys状态[156]) << endl;
				if (input.m_Key.Keys状态[k] == DEF_按键状态_按下中) {
					input.m_Key.Keys状态[k] = DEF_按键状态_放开;
					//std::cout<<"main ui event : "<<int32(k)<<std::endl;
				}
			}
		}

		for (uint16 k = 0; k < 8; ++k) {
			if (gm->鼠标按键状态[k]) {
				gm->有输入事件 = true;
			}
		}

	}



	if (gm->m_当前拖拽部件) {
		if (gm->执行鼠标点击) {
			gm->执行鼠标点击 = false;
		}

		if (鼠标移动了 && gm->拖放状态 == DEF_拖放状态_开始拖放 && gm->m_当前拖拽部件->mf_开始拖拽) {
			gm->m_拖放数据 = {};
			gm->m_当前拖拽部件->mf_开始拖拽(gm->m_当前拖拽部件, C_Widget::g_鼠标, gm->m_拖放数据);
			gm->拖放状态 = DEF_拖放状态_拖放;
		}

		if (gm->拖放状态 == DEF_拖放状态_拖放) {
			事件是否传递 = gm->m_当前拖拽部件->mf_拖拽(gm->m_当前拖拽部件, C_Widget::g_鼠标, gm->m_拖放数据);
			++鼠标移动距离;
			if (事件是否传递 == E_事件是否传递::e_事件传递_终止) {
				goto To_鼠标键盘事件处理;
			}
		}
	}




	/*****************************************************************************************
	*                                 执行全局按键事件
	*****************************************************************************************/
	
	//gm->是否执行UI部件事件 = !f_执行全局按键事件(input);
	if (f_执行全局键盘事件(input)) {
		goto To_按键状态设置;
	}



	if (全局鼠标事件数量) {
		auto* 全局鼠标事件 = g_全局鼠标事件.data();
		for (uint32 i = 0; i < 全局鼠标事件数量; ++i) {
			if (f_event_执行鼠标事件(&全局鼠标事件[i], input.m_Key.Keys状态, gm->鼠标按键状态)) {
				全局鼠标事件[i].event(nullptr, 0);
				goto To_按键状态设置;
			}
		}
	}
	

	static C_Widget* g鼠标进入组件堆栈[256];
	static int32 g鼠标进入组件堆栈数量 = -1;
	
	/*****************************************************************************************
	*                           上次多出部件 执行鼠标移出事件
	*****************************************************************************************/
	if (gm->m_上一次焦点组件数量 > C_Widget::g_焦点数量) {
		for (int8 i = gm->m_上一次焦点组件数量; i > C_Widget::g_焦点数量; ) {
			--i;
			if(gm->m_上一次焦点组件[i] && gm->m_上一次焦点组件[i]->mf_鼠标离开) 
				gm->m_上一次焦点组件[i]->mf_鼠标离开(gm->m_上一次焦点组件[i], C_Widget::g_鼠标);
			gm->m_上一次焦点组件[i] = 0;
		}
	}

	//for (int32 i = g鼠标进入组件堆栈数量; i >= 0; --i) {
	//	auto 当前执行组件 = g鼠标进入组件堆栈[i];
	//	if (当前执行组件) {
	//		bool 执行 = true;
	//		for (int32 j = 0; j < gm->m_上一次焦点组件数量; ++j) {
	//			if (gm->m_上一次焦点组件[j] == 当前执行组件) {
	//				执行 = false;
	//				break;
	//			}
	//		}
	//		if (执行 && 当前执行组件->mf_鼠标离开) {
	//			当前执行组件->mf_鼠标离开(当前执行组件, C_Widget::g_鼠标);
	//
	//			g鼠标进入组件堆栈[i] = nullptr;
	//		}
	//	}
	//}



To_鼠标键盘事件处理:

	for (int8 i = C_Widget::g_焦点数量; i > 0 ; ) {
		--i;
		
		C_Widget* w;
		if (C_文本框::g当前操作文本框) {
			w = C_文本框::g当前操作文本框;
		}
		w = g_焦点组件[i];
		

		/*****************************************************************************************
		*        上次记录部件 不同就执行上次记录鼠标移除事件 执行当前部件鼠标进入事件
		*****************************************************************************************/
		if (事件是否传递 == E_事件是否传递::e_事件传递_继续 && gm->m_上一次焦点组件[i] != w) {
			if (gm->m_上一次焦点组件[i] != 0) {
				if (i < gm->m_上一次焦点组件数量) {
					if (gm->m_上一次焦点组件[i]->mf_鼠标离开) gm->m_上一次焦点组件[i]->mf_鼠标离开(gm->m_上一次焦点组件[i], C_Widget::g_鼠标);
				}
				//if (i > g鼠标进入组件堆栈数量) {
				//	if (gm->m_上一次焦点组件[i]->mf_鼠标离开) gm->m_上一次焦点组件[i]->mf_鼠标离开(gm->m_上一次焦点组件[i], C_Widget::g_鼠标);
				//}
			}

			
			if (w->mf_鼠标进入) {
				w->mf_鼠标进入(w, C_Widget::g_鼠标);

				//++g鼠标进入组件堆栈数量;
				//g鼠标进入组件堆栈[g鼠标进入组件堆栈数量] = w;
			}

			//记录以执行鼠标进入事件
			gm->m_上一次焦点组件[i] = w;
		}
		




		bool 不向下传递 = false;

		//鼠标左键事件
		{
			if (gm->鼠标按键状态[E_Input_鼠标按键::e_左键] == DEF_按键状态_按下 && gm->鼠标左键按下传递) {
				
				gm->鼠标左键按下传递 = w->mf_鼠标按键按下(w, E_鼠标按钮::e_鼠标左键);
				


				//==================== 双击开始计时 =====================
				g时间end = clock();
				gdur = (double)(g时间end - g时间start);
				gdur = (gdur * 1000 / CLOCKS_PER_SEC);

				if (gdur > S_UI主题::ui_双击时间间隔) {
					g时间start = clock();
					g_上一轮焦点组件 = w;
					gm->执行鼠标点击 = true;
				}
				else if (g_上一轮焦点组件 == w) {
					if (w->mf_鼠标按键双击) {
						gm->鼠标左键按下传递 |= w->mf_鼠标按键双击(w, E_鼠标按钮::e_鼠标左键);
						g双击时间 = 0;
					}
					gm->执行鼠标点击 = false;
				}


				
				if (gm->m_当前操作部件 == 0) gm->m_当前操作部件 = w;
				
				//判断最顶层组件
				if (C_Widget::g_焦点数量 - i == 1) {
					f_ui_文本部件完成输入(w);
				}
				
				
				
				//==================== 开始拖放事件 ====================
				if (w->mf_拖拽 && gm->拖放状态 == DEF_拖放状态_准备) {
					gm->拖放状态 = DEF_拖放状态_开始拖放;
					gm->m_当前拖拽部件 = w;
					鼠标移动距离 = 0;
				}
			}


			if (gm->鼠标按键状态[E_Input_鼠标按键::e_左键] == DEF_按键状态_放开 && gm->鼠标左键放开传递) {
				gm->鼠标左键放开传递 = w->mf_鼠标按键放开(w, E_鼠标按钮::e_鼠标左键);

				if (gm->m_当前操作部件 == w) {
					w->mf_鼠标按键点击(w, E_鼠标按钮::e_鼠标左键);
					gm->m_当前操作部件 = nullptr;
					
				}

				if (gm->m_当前拖拽部件 && gm->m_当前拖拽部件->mf_结束拖拽 && gm->拖放状态 == DEF_拖放状态_拖放) {
					E_事件是否传递 拖放传递 = E_事件是否传递(gm->m_当前拖拽部件->mf_结束拖拽(gm->m_当前拖拽部件, w, gm->m_拖放数据));
					if (w->mf_结束拖拽 && w != gm->m_当前拖拽部件) w->mf_结束拖拽(w, gm->m_当前拖拽部件, gm->m_拖放数据);

					gm->m_当前拖拽部件 = nullptr;
					gm->拖放状态 = DEF_拖放状态_准备;
					gm->执行鼠标点击 = false;

					
					if(拖放传递 == E_事件是否传递::e_事件传递_终止) break;
				}

				鼠标移动距离 = 0;
				gm->m_当前拖拽部件 = nullptr;
				gm->拖放状态 = DEF_拖放状态_准备;
				gm->执行鼠标点击 = false;

			}
			else if (gm->鼠标按键状态[E_Input_鼠标按键::e_左键] == DEF_按键状态_放开) {
				w->mf_鼠标按键放开(w, E_鼠标按钮::e_鼠标左键);
				gm->m_当前拖拽部件 = nullptr;
				鼠标移动距离 = 0;
			}
		}

		//鼠标右键事件
		{
			if (gm->鼠标按键状态[E_Input_鼠标按键::e_右键] == DEF_按键状态_按下) {
				w->mf_鼠标按键按下(w, E_鼠标按钮::e_鼠标右键);
			}
			else if (gm->鼠标按键状态[E_Input_鼠标按键::e_右键] == DEF_按键状态_放开) {
				w->mf_鼠标按键放开(w, E_鼠标按钮::e_鼠标右键);
			}
		}

		//鼠标中键事件
		{
			if (gm->鼠标按键状态[E_Input_鼠标按键::e_中键] == DEF_按键状态_按下) {
				w->mf_鼠标按键按下(w, E_鼠标按钮::e_鼠标中键);
			}
			else if (gm->鼠标按键状态[E_Input_鼠标按键::e_中键] == DEF_按键状态_放开) {
				w->mf_鼠标按键放开(w, E_鼠标按钮::e_鼠标中键);
			}
		}

		//鼠标移动
		{
			if (((S_鼠标属性*)input.m_鼠标)->lX || ((S_鼠标属性*)input.m_鼠标)->lY) {
				w->mf_鼠标移动(w, Mouse);
			}
		}

		//鼠标滚轮
		{
			if (((S_鼠标属性*)input.m_鼠标)->lZ && w->mf_鼠标滚轮) {
				w->mf_鼠标滚轮(w, C_Widget::g_鼠标);
			}
		}



		/************************************************************************/
		//                             键盘按键事件
		/************************************************************************/
		if (gm->键盘按键向下传递) {
			//C_Widget* 键盘接收组件 = C_文本框::g当前操作文本框 ? C_文本框::g当前操作文本框 : w;
			//if (键盘接收组件->mf_键盘按键敲击) gm->键盘按键向下传递 = 键盘接收组件->mf_键盘按键敲击(键盘接收组件, input.m_Key);

			if (C_文本框::g当前操作文本框) {
				if (C_文本框::g当前操作文本框->mf_键盘按键敲击) {
					gm->键盘按键向下传递 = C_文本框::g当前操作文本框->mf_键盘按键敲击(C_文本框::g当前操作文本框, input.m_Key);
					break;
				}
			}
			else {
				if (w->mf_键盘按键敲击) gm->键盘按键向下传递 = w->mf_键盘按键敲击(w, input.m_Key);
			}
		}
		

		if (f_event_执行键位绑定事件(C_文本框::g当前操作文本框 ? *C_文本框::g当前操作文本框 : *w, *gm, input)) {
			goto To_按键状态设置;
		}

		if (i > C_Widget::g_焦点数量) 
			break;
	}


	To_按键状态设置:

	//==== 记录上次记录部件以执行事件 ====
	gm->m_上一次焦点组件数量 = C_Widget::g_焦点数量;
	{
		if (gm->鼠标按键状态[E_Input_鼠标按键::e_左键] == DEF_按键状态_放开) {
			gm->m_当前操作部件 = 0;
		}

		for (uint8 i = 0; i < 6; ++i) {
			if (gm->鼠标按键状态[i] == DEF_按键状态_按下) {
				gm->鼠标按键状态[i] = DEF_按键状态_按下中;
			}
			else if (gm->鼠标按键状态[i] == DEF_按键状态_放开) {
				gm->鼠标按键状态[i] = DEF_按键状态_准备;
			}
		}

		for (uint16 k = 0; k < 256; ++k) {
			if (input.m_Key.Keys状态[k] == DEF_按键状态_按下) {
				input.m_Key.Keys状态[k] = DEF_按键状态_按下中;
			}
			else if (input.m_Key.Keys状态[k] == DEF_按键状态_放开) {
				input.m_Key.Keys状态[k] = DEF_按键状态_准备;
			}
		}

	}

	To_结尾鼠标数据更新:
	C_Widget::g_鼠标.abs = C_Widget::g_鼠标.gPos;
	//std::cout << "输入事件" << std::endl;
}




static void f_更新UI动画(C_Widget* w) {
	if (w->mf_动画更新) {
		w->mf_动画更新(w);
	}


	uint32 num = w->m_子组件.size();
	if (num) {
		auto* p = w->m_子组件.data();

		for (uint32 i = 0; i < num; ++i) {
			f_更新UI动画(p[i]);
		}
	}
}

static bool f_更新UI部件布局(C_Widget* w, bool is需裁剪) {
	auto* p = w->m_子组件.data();
	uint32 num = w->m_子组件.size();

	if (w->m_绘制属性更新) {
		if (w->mf_布局Fun) w->mf_布局Fun(w, p, num);
		
		is需裁剪 = true;
	}

	if (is需裁剪) w->f_裁剪();
	if (num) {
//#pragma omp parallel for
		for (int32 i = 0; i < num; ++i) {
			bool 是否更新绘制组件 = f_更新UI部件布局(p[i], is需裁剪);
		}
	}

	return is需裁剪;
}

static void f_更新UI部件属性(C_Widget* w, bool is需裁剪) {
	
	if (w->m_绘制属性更新) {
		if (w->m_画布 && w->mf_变换修改) w->mf_变换修改(w);
		
		is需裁剪 = true;
		w->m_绘制属性更新 = false;
	}
	
	uint32 num = w->m_子组件.size();
	if (num) {
		auto* p = w->m_子组件.data();
//#pragma omp parallel for
		for (int32 i = 0; i < num; ++i) {
			f_更新UI部件属性(p[i], is需裁剪);
		}
	}

	w->m_显示 = false;
}


void f_ui_更新UI部件属性(C_Widget管理* gm, ivec2 view) {
	/*******************************************************************/
	//                         Vulkan 缓存数据处理
	/*******************************************************************/
	if (g_纹理填充列队.size()) {
		for (auto& e : g_纹理填充列队) {
			f_tex_修改大小(e.m_Tex, e.m_Dim);
			f_tex_填充纹理数据(e.m_Tex, e.m_Data, sizeof(S_RGBA8UI), e.m_Dim);
		}
		g_纹理填充列队.clear();
	}


	/*******************************************************************/
	//                         顶层窗口属性
	/*******************************************************************/
	auto e = f_widget_getTop();
	for (uint8 i = 0; i < e.m_Num; ++i) {
		f_更新UI部件布局(e.m_W[i], false);
		f_更新UI动画(e.m_W[i]);
	}
	for (uint8 i = 0; i < e.m_Num; ++i) {
		f_更新UI部件属性(e.m_W[i], false);
		//f_更新UI动画(e.m_W[i]);
	}

	/*******************************************************************/
	//                         常规窗口属性
	/*******************************************************************/

	//即时更新部件随窗口大小
	if (gm->m_Root->m_绘制属性更新) {
		gm->m_Root->m_裁剪大小 = { 0.0f,0.0f, float32(view.x), float32(view.y) };
		gm->m_Root->f_setSize(f_vec_F(view));
	}

	f_更新UI部件布局(gm->m_Root, false);
	
	f_更新UI动画(gm->m_Root);
	f_更新UI部件属性(gm->m_Root, false);

	gm->mf_输入执行后回调();


}

void f_ui_动态销毁UI部件(C_Widget管理* gm) {
	if (f_widget_待销毁部件清理()) {
		gm->m_当前拖拽部件 = nullptr;
	}
}






void f_ui_绘制组件(C_Widget管理* gm) {
	/*******************************************************************/
	//                         绘制顶层窗口
	/*******************************************************************/
	auto e = f_widget_getTop();
	for (uint8 i = 0; i < e.m_Num; ++i) {
		e.m_W[i]->f_绘图(0, gm->m_投影矩阵);
	}

	gm->m_Root->f_绘图(0, gm->m_投影矩阵);
}

void f_ui_绘制到屏幕(C_Widget管理* gm, ivec2 view) {
	auto ortho = OrthographicMatrix(0, view.x, 0, view.y, -1000.0, 1000.0);
	//Mat44 位置 = Mat44::kIdentity;

	std::vector<Mat44f> mat(1);
	//mat[0] = *((Mat44f*)&(ortho * 位置));
	mat[0] = *((Mat44f*)&(ortho));
	f_fill板载缓存(gm->m_投影矩阵, mat, E_板载缓存类型::e_UBO, gm->m_UICtx->m_Ctx);



	gm->视口 = { 0.0f,0.0f, float32(view.x), float32(view.y), 0.0f, 1.0f }; ///
	gm->裁剪 = { {0,0}, {uint32(view.x), uint32(view.y)} };

	gm->m_渲染参数.m_视图投影矩阵 = gm->m_投影矩阵;
	gm->m_渲染参数.m_视口 = &gm->视口;
	gm->m_渲染参数.m_裁剪 = &gm->裁剪;
	

	//f_setGPU参数布局(gm->m_投影矩阵, gm->m_视口GPU参数设置);
	/*******************************************************************/
	//                         帧缓冲绘制
	/*******************************************************************/


	/*******************************************************************/
	//                         常规窗口绘制到屏幕
	/*******************************************************************/
	gm->f_绘制子组件(gm->m_Root, gm->m_渲染参数);


	/*******************************************************************/
	//                         顶层窗口绘制到屏幕
	/*******************************************************************/
	auto e = f_widget_getTop();
	for (uint8 i = 0; i < e.m_Num; ++i) {
		gm->f_绘制子组件(e.m_W[i], gm->m_渲染参数);
	}

}

void f_ui_统一映射GPU内存() {
	f_scene_渲染器GPU内存映射();

}

void f_ui_统一解映射GPU内存() {
	f_scene_渲染器GPU内存解映射();

}

void f_ui_统一分配GPU内存() {
	f_scene_渲染器分配GPU内存();
	f_scene_物体GPU内存分配();
}






void f_ui_push纹理填充(S_纹理* tex, uint8* data, uvec3 dim) {
	if (g_纹理填充列队.size() == 0) {
		g_纹理填充列队.push_back({ dim, tex, data });
	}
}

void f_ui_run纹理填充() {
	
}


uint16 f_ui_管理器添加根部件(C_Widget管理* gm, C_Widget* w) {
	gm->m_根部件切换组.push_back(w);
	w->m_实例ID = gm->m_根部件切换组.size() - 1;
	w->f_绑定窗口管理(gm);
	return w->m_实例ID;
}

void f_ui_switchRootWidget(C_Widget管理* gm, uint16 id) {
	if (gm->m_Root->mf_打开关闭) gm->m_Root->mf_打开关闭(gm->m_Root, false);
	gm->m_Root = gm->m_根部件切换组[id];
	gm->m_Root->m_绘制属性更新 = true;

	if (gm->m_Root->mf_打开关闭) gm->m_Root->mf_打开关闭(gm->m_Root, true);
}

vec2 f_ui_get空间投影比例(const S_Rect2Df& rect, C_Mat44& 投影矩阵, float32 视点距离) {
	auto mat = C_Mat44::kIdentity;
	mat.columns[3][2] = 视点距离;

	vec2 coord = f_Project空间坐标转屏幕(投影矩阵, mat, { 0, 0, 0 }, rect);
	vec2 coord2 = f_Project空间坐标转屏幕(投影矩阵, mat, { 1, 1, 0 }, rect);

	return coord2 - coord;
}

vec2 f_ui_get空间投影比例(const S_Rect2Df& rect, const S_摄像机& 摄像机) {
	auto mat = C_Mat44::kIdentity;
	mat.columns[3][2] = 摄像机.m_视点距离;

	vec2 coord = f_Project空间坐标转屏幕(摄像机.m_相机投影, mat, { 0, 0, 0 }, rect);
	vec2 coord2 = f_Project空间坐标转屏幕(摄像机.m_相机投影, mat, { 1, 1, 0 }, rect);
	return coord2 - coord;
}

void f_ui_注册全局快捷键(std::vector<uint8>& Key, fp_Widget全局按键按下 func) {
	uint64 k = 0;
	uint8 num = Key.size();
	for (uint8 i = 0; i < num; ++i) {
		k |= (Key[i] << (i*8));
	}

	k |= (uint64(num) << (7*8));

	g_全局按键事件[k] = func;
	//g_全局按键事件.key_comp();
}

void f_ui_注册全局快捷键(const S_键盘键位映射& Key) {
	g_全局键盘事件.push_back(Key);
}

void f_ui_注册全局鼠标快捷键(const S_鼠标键位映射& Key) {
	g_全局鼠标事件.push_back(Key);
}

void f_ui_注册键盘快捷键(C_Widget* self, E_键位操作类型 操作类型, fp_Widget快捷键事件 event, uint8 any, bool ctrl, bool shift, bool alt) {
	S_键盘键位映射* km = (S_键盘键位映射*)malloc(sizeof(S_键盘键位映射));
	(*km) = {};
	km->event = event;
	km->键盘按键[3] = any;

	switch (操作类型) {
	case E_键位操作类型::e_键位_按下: 
		km->键盘状态[3] = DEF_按键状态_按下;
		break;
	case E_键位操作类型::e_键位_放开:
		km->键盘状态[3] = DEF_按键状态_放开;
		break;
	default:
		break;
	}
	
	self->m_键位映射.push_back((S_键位映射*)km);
}

void f_ui_注册鼠标快捷键(C_Widget* self, E_键位操作类型 操作类型, fp_Widget快捷键事件 event, E_Input_鼠标按键 any, bool ctrl, bool shift, bool alt) {
	S_鼠标键位映射* km = (S_鼠标键位映射*)malloc(sizeof(S_鼠标键位映射));
	(*km) = {};
	km->event = event;
	(*km->键盘按键) = {};
	(*km->键盘状态) = {};
	self->m_键位映射.push_back((S_键位映射*)km);
}

void f_ui_注册键盘快捷键(C_Widget* self, S_键盘键位映射* km) {
	//km->发生组件 = self;
	self->m_键位映射.push_back((S_键位映射*)km);
}

void f_ui_注册鼠标快捷键(C_Widget* self, S_键位映射* km) {
	//km->发生组件 = self;
	for (auto& e : self->m_键位映射) {
		if (e == km) {
			return;
		}
	}
	self->m_键位映射.push_back((S_键位映射*)km);
}







void f_ui添加图标组(C_Widget管理* gm, std::vector<S_纹理组添加参数> 添加参数) {
	for (auto& e : 添加参数) {
		gm->f_加载图标(e.m_GroupName, e.m_Path);
	}
}

void f_ui加载字体(S_UI创建环境* ctx, const std::vector<S_字体加载参数>& 添加参数){
	for (auto& e : 添加参数) {
		f_surface_加载字体(*ctx, e);
	}
}


void f_ui_释放图标组(C_Widget管理* gm) {
	for (auto& e : gm->m_UICtx->m_Mat->m_ICOs) {
		f_tex_销毁纹理(e.second.m_Tex);
	}
}

void f_ui_释放字体(C_Widget管理* gm) {
	for (auto& e : gm->m_UICtx->m_Mat->m_Fonts) {
		f_tex_销毁纹理(e.second.m_Tex);
	}
}





void f_ui_文件拖入(C_Widget管理* gm, const vec2& point) {
	f_ui_筛选焦点组件(gm, point);

	if (C_Widget::g_焦点数量) {
		C_Widget* w = g_焦点组件[C_Widget::g_焦点数量 - 1];

		if (w->mf_文件处理回调 && C_Widget管理::m_拖放文件名.size()) {
			auto path = f_WString组ToString组(C_Widget管理::m_拖放文件名, "utf-8");
			for (auto& e : path) {
				std::cout << "拖放路径:" << e << std::endl;
			}
			w->mf_文件处理回调(w, path, E_对话框类型::e_关闭);
			C_Widget管理::m_拖放文件名.clear();
		}
	}
}






/*void f_帧缓冲绘制屏幕(C_Widget管理* gm) {
	for (auto& e : gm->m_帧渲染层) {
		C_3D视口* view = dynamic_cast<C_3D视口*>(e);
		f_Draw_Begin(view->m_Face->m_Ctx, view->m_Face->m_帧缓存, view->m_Face->m_交换ID);
		view->m_Scene->f_Update();
		view->m_Scene->f_Render(view->m_Size);
		f_Draw_end(view->m_Face->m_Ctx);
		if (view->m_Face->m_交换ID >= 1) view->m_Face->m_交换ID = 0;
		else ++view->m_Face->m_交换ID;
	}
}*/

/*void f_更新UI动画(C_Widget管理* gm) {
	f_更新UI动画(gm->m_Root);
}*/


